/** 
 * File-Name:ExceptionRepository.java
 *
 * Created on 2011-4-20 下午07:12:31
 * 
 * @author: Neo (neolimeng@gmail.com)
 * Software Engineering Institute, Peking University, China
 * 
 * Copyright (c) 2009, Peking University
 * 
 *
 */
package com.exceptionhandler.service.exception;

import java.sql.Connection;
import java.util.List;

import org.apache.commons.dbutils.DbUtils;
import org.apache.log4j.Logger;

import com.exceptionhandler.dao.ExceptionInfoDao;
import com.exceptionhandler.dao.StackInfoDao;
import com.exceptionhandler.dao.support.DaoSupport;
import com.exceptionhandler.entity.ExceptionInfo;
import com.exceptionhandler.entity.StackInfo;
import com.exceptionhandler.service.CommonService;
import com.exceptionhandler.service.api.APIRepository;

/**
 * Description: Repository for exception related information, like
 * ExceptionInfo, StackInfo, etc.
 * 
 * @author: Neo (neolimeng@gmail.com) Software Engineering Institute, Peking
 *          University, China
 * @version 1.0 2011-4-20 下午07:12:31
 */
public class ExceptionRepository extends CommonService {
	private static Logger log = Logger.getLogger(ExceptionRepository.class);

	public static synchronized String save(ExceptionInfo exceptionInfo) {
		String returnMessage = UNKNOWN;
		String SAVE_EXCEPTION_INFO_SQL = "INSERT INTO exceptioninfo (uuid, fullName, tip, url, stackTraceString, entityStatus, entityDatetime, reserve01, reserve02, reserve03, reserve04, reserve05) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
		String SAVE_STACK_INFO_SQL = "INSERT INTO stackinfo (position, methodName, fileName, lineNum, exceptionId, apiId, entityStatus, entityDatetime) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";

		Connection connection = DaoSupport.getConnection();
		ExceptionInfoDao exceptionInfoDao = new ExceptionInfoDao();
		StackInfoDao stackInfoDao = new StackInfoDao();

		try {
			// First, save ExceptionInfo.
			Object[] exceptionInfoParams = { exceptionInfo.getUuid(),
					exceptionInfo.getFullName(), exceptionInfo.getTip(),
					exceptionInfo.getUrl(),
					exceptionInfo.getStackTraceString(),
					exceptionInfo.getEntityStatus(),
					exceptionInfo.getEntityDatetime(),
					exceptionInfo.getReserve01(), exceptionInfo.getReserve02(),
					exceptionInfo.getReserve03(), exceptionInfo.getReserve04(),
					exceptionInfo.getReserve05() };
			exceptionInfoDao.execute(connection, SAVE_EXCEPTION_INFO_SQL,
					exceptionInfoParams);

			// Second, get the Id of the ExceptionInfo.
			List<ExceptionInfo> exceptionInfos = exceptionInfoDao
					.getByProperty(connection, "uuid", "'"
							+ exceptionInfo.getUuid() + "'");
			if (exceptionInfos == null || exceptionInfos.size() != 1) {
				log.error("Error when getting ExceptionInfo Id using uuid.");
				returnMessage = ERROR;
			} else {
				long exceptionInfoId = exceptionInfos.get(0).getId();
				// Third, save the exception StackInfos.
				List<StackInfo> stackTrace = exceptionInfo.getStackTrace();

				if (stackTrace == null || stackTrace.size() == 0) {
					log.info("No stack trace info!");
				} else {
					for (int i = 0; i < stackTrace.size(); i++) {
						StackInfo stackInfo = stackTrace.get(i);

						// 1. Save API info.
						String result = APIRepository.save(stackInfo
								.getApiInfo());

						if (APIRepository.SAVE_SUCCESS.equals(result)
								|| APIRepository.SAVE_ALREADY_EXIST
										.equals(result)) {

							// 2. Get API Id.
							System.err.println("Is stackInfo null?"
									+ (stackInfo == null));
							System.err
									.println("Is stackInfo.getApiInfo() null?"
											+ (stackInfo.getApiInfo() == null));
							System.err
									.println("Is stackInfo.getApiInfo().getMethodName() null?"
											+ (stackInfo.getApiInfo()
													.getMethodName() == null));
							System.err
									.println("Is APIRepository.get(stackInfo.getApiInfo().getMethodName()) null?"
											+ (APIRepository.get(stackInfo
													.getApiInfo()
													.getMethodName()) == null));

							long apiId = APIRepository.get(
									stackInfo.getApiInfo().getMethodName())
									.getId();

							// 3. Save stack info.
							Object[] stackInfoParams = {
									stackInfo.getPosition(),
									stackInfo.getMethodName(),
									stackInfo.getFileName(),
									stackInfo.getLineNum(), exceptionInfoId,
									apiId, stackInfo.getEntityStatus(),
									stackInfo.getEntityDatetime() };
							stackInfoDao.execute(connection,
									SAVE_STACK_INFO_SQL, stackInfoParams);
						} else {
							log
									.error("Errors occur when saving apiInfo, bypass this stackInfo");
						}
					}
				}
				returnMessage = SUCCESS;
			}
		} catch (Exception e) {
			e.printStackTrace();
			returnMessage = EXCEPTION;
		} finally {
			try {
				DbUtils.close(connection);
			} catch (Exception e2) {
				e2.printStackTrace();
				returnMessage = EXCEPTION;
			}
		}
		return returnMessage;
	}

	public static synchronized ExceptionInfo get(long exceptionInfoId) {
		ExceptionInfoDao exceptionInfoDao = new ExceptionInfoDao();
		StackInfoDao stackInfoDao = new StackInfoDao();

		ExceptionInfo exceptionInfo = null;
		Connection connection = DaoSupport.getConnection();
		try {
			// First, get ExceptionInfo.
			exceptionInfo = exceptionInfoDao.getById(connection,
					exceptionInfoId);

			if (exceptionInfo != null) {
				// Second, get the exception stack trace info.
				List<StackInfo> stackTrace = stackInfoDao.getByProperty(
						connection, "exceptionId", exceptionInfoId);

				if (stackTrace != null && stackTrace.size() > 0) {
					exceptionInfo.setStackTrace(stackTrace);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				DbUtils.close(connection);
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return exceptionInfo;
	}

	/**
	 * Description:
	 * 
	 * @param args
	 *            void
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
